package com.usefullc.common.util;

import com.google.common.collect.Lists;

import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.time.temporal.TemporalAdjusters;
import java.time.temporal.TemporalUnit;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 *
 */
public final class LocalDateTimeUtils {

    private LocalDateTimeUtils() {

    }

    /**
     * Date转换为LocalDateTime.
     *
     * @param date
     * @return java.time.LocalDateTime
     */
    public static LocalDateTime convertDateToLDT(Date date) {
        return LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());
    }

    /**
     * LocalDateTime转换为Date.
     *
     * @param time
     * @return java.util.Date
     */
    public static Date convertLDTToDate(LocalDateTime time) {
        return Date.from(time.atZone(ZoneId.systemDefault()).toInstant());
    }

    /**
     * 转换毫秒值为日期
     *
     * @param millis
     * @return
     */
    public static LocalDateTime convertMilliToLDT(long millis) {
        return LocalDateTime.ofInstant(Instant.ofEpochMilli(millis), ZoneId.systemDefault());
    }

    /**
     * 将日期化为毫秒.
     *
     * @param time
     * @return java.lang.Long
     */
    public static Long getMilliByTime(LocalDateTime time) {
        return time.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
    }

    /**
     * 将日期化为秒.
     *
     * @param time
     * @return java.lang.Long
     */
    public static Long getSecondsByTime(LocalDateTime time) {
        return time.atZone(ZoneId.systemDefault()).toInstant().getEpochSecond();
    }

    /**
     * 时间格式化.
     *
     * @param time
     * @param pattern
     * @return java.lang.String
     */
    public static String formatTime(LocalDateTime time, String pattern) {
        return time.format(DateTimeFormatter.ofPattern(pattern));
    }

    /**
     * 日期加上一个数,根据field不同加不同值,field为ChronoUnit.*.
     *
     * @param time
     * @param number
     * @param field
     * @return java.time.LocalDateTime
     */
    public static LocalDateTime plus(LocalDateTime time, long number, TemporalUnit field) {
        return time.plus(number, field);
    }

    /**
     * 日期减去一个数,根据field不同减不同值,field参数为ChronoUnit.*.
     *
     * @param time
     * @param number
     * @param field
     * @return java.time.LocalDateTime
     */
    public static LocalDateTime minu(LocalDateTime time, long number, TemporalUnit field) {
        return time.minus(number, field);
    }

    /**
     * 获取两个日期的差  field参数为ChronoUnit.*.
     *
     * @param startTime
     * @param endTime
     * @param field
     * @return long
     */
    public static long betweenTwoTime(LocalDateTime startTime, LocalDateTime endTime, ChronoUnit field) {
        return field.between(startTime, endTime);
    }

    /**
     * 获取一天的开始时间，2017,7,22 00:00.
     *
     * @param day
     * @return java.time.LocalDateTime
     */
    public static LocalDateTime getDayStart(LocalDate day) {
        return LocalDateTime.of(day, LocalTime.MIN);
    }

    /**
     * 获取一天的结束时间，2017,7,22 23:59:59.999999999.
     *
     * @param day
     * @return java.time.LocalDateTime
     */
    public static LocalDateTime getDayEnd(LocalDate day) {
        return LocalDateTime.of(day, LocalTime.MAX);
    }

    public static boolean isAfter(LocalDateTime arg1, LocalDateTime arg2) {
        return arg1.isAfter(arg2);
    }

    public static boolean isBefore(LocalDateTime arg1, LocalDateTime arg2) {
        return arg1.isBefore(arg2);
    }

    public static boolean isEqual(LocalDateTime arg1, LocalDateTime arg2) {
        return arg1.isEqual(arg2);
    }

    /**
     * 获取当天对应的星期数
     *
     * @return: java.lang.Integer
     */
    public static Integer getTodayOfWeek() {
        return LocalDate.now().getDayOfWeek().getValue();
    }

    /**
     * @param localDate
     * @Description: 获取指定日期对应的星期数
     * @return: java.lang.Integer
     */
    public static Integer getDayOfWeek(LocalDate localDate) {
        return localDate.getDayOfWeek().getValue();
    }

    /**
     * 获取指定日期对应的星期数
     *
     * @param localDateTime
     * @return: java.lang.Integer
     */
    public static Integer getDayOfWeek(LocalDateTime localDateTime) {
        return localDateTime.getDayOfWeek().getValue();
    }

    /**
     * 获取当天所属星期的指定星期对应的时间
     *
     * @param dayOfWeek
     * @return: java.time.LocalDateTime
     */
    public static LocalDateTime getTimeOfTodayOfWeek(DayOfWeek dayOfWeek) {
        return LocalDateTime.now().with(TemporalAdjusters.previousOrSame(dayOfWeek));
    }

    /**
     * 获取指定时间所属星期的指定星期对应的时间
     *
     * @param localDateTime
     * @param dayOfWeek
     * @return: java.time.LocalDateTime
     */
    public static LocalDateTime getTimeOfDayOfWeek(LocalDateTime localDateTime, DayOfWeek dayOfWeek) {
        return localDateTime.with(TemporalAdjusters.previousOrSame(dayOfWeek));
    }

    /**
     * 获取当天所属星期的指定星期对应的日期
     *
     * @param dayOfWeek
     * @return: java.time.LocalDateTime
     */
    public static LocalDate getDateOfTodayOfWeek(DayOfWeek dayOfWeek) {
        return LocalDate.now().with(TemporalAdjusters.previousOrSame(dayOfWeek));
    }

    /**
     * 获取指定时间所属星期的指定星期对应的日期
     *
     * @param localDate
     * @param dayOfWeek
     * @return: java.time.LocalDateTime
     */
    public static LocalDate getDateOfDayOfWeek(LocalDate localDate, DayOfWeek dayOfWeek) {
        return localDate.with(TemporalAdjusters.previousOrSame(dayOfWeek));
    }

    /**
     * 将locadate转为date
     *
     * @param date
     * @return: java.util.Date
     */
    public static Date convertLDToDate(LocalDate date) {
        return Date.from(date.atStartOfDay(ZoneId.systemDefault()).toInstant());
    }

    /**
     * 获取两个日期之间的所有日期
     * @param startDate
     * @param endDate
     * @return
     */
    public static List<LocalDate> durationBetweenTwoDate(LocalDate startDate, LocalDate endDate) {
        long between = ChronoUnit.DAYS.between(startDate, endDate);
        if (between <= 0) {
            return Lists.newArrayList();
        }
        return Stream.iterate(startDate, localDate -> localDate.plusDays(1))
                .limit(between + 1)
                .collect(Collectors.toList());
    }

    /**
     * 获取两个日期的差  field参数为ChronoUnit.*.
     *
     * @param startDate
     * @param endDate
     * @param field
     * @return long
     */
    public static long betweenTwoDate(LocalDate startDate, LocalDate endDate, ChronoUnit field) {
        return field.between(startDate, endDate);
    }

}
